﻿//
// XN4SL - Xna Framework for Silverlight.
//
namespace Xn4Sl.Framework
{
    /// <summary>
    /// Defines a matrix.
    /// </summary>
    public struct Matrix
    {
        /// <summary>
        /// Value at row 1 column 1 of the matrix.
        /// </summary>
        public float M11;
        /// <summary>
        /// Value at row 1 column 2 of the matrix.
        /// </summary>
        public float M12;
        /// <summary>
        /// Value at row 1 column 3 of the matrix.
        /// </summary>
        public float M13;
        /// <summary>
        /// Value at row 1 column 4 of the matrix.
        /// </summary>
        public float M14;
        /// <summary>
        /// Value at row 2 column 1 of the matrix.
        /// </summary>
        public float M21;
        /// <summary>
        /// Value at row 2 column 2 of the matrix.
        /// </summary>
        public float M22;
        /// <summary>
        /// Value at row 2 column 3 of the matrix.
        /// </summary>
        public float M23;
        /// <summary>
        /// Value at row 2 column 4 of the matrix.
        /// </summary>
        public float M24;
        /// <summary>
        /// Value at row 3 column 1 of the matrix.
        /// </summary>
        public float M31;
        /// <summary>
        /// Value at row 3 column 2 of the matrix.
        /// </summary>
        public float M32;
        /// <summary>
        /// Value at row 3 column 3 of the matrix.
        /// </summary>
        public float M33;
        /// <summary>
        /// Value at row 3 column 4 of the matrix.
        /// </summary>
        public float M34;
        /// <summary>
        /// Value at row 4 column 1 of the matrix.
        /// </summary>
        public float M41;
        /// <summary>
        /// Value at row 4 column 2 of the matrix.
        /// </summary>
        public float M42;
        /// <summary>
        /// Value at row 4 column 3 of the matrix.
        /// </summary>
        public float M43;
        /// <summary>
        /// Value at row 4 column 4 of the matrix.
        /// </summary>
        public float M44;

        /// <summary>
        /// Initializes a new instance of Matrix.
        /// </summary>
        public Matrix(float m11, float m12, float m13, float m14,
                      float m21, float m22, float m23, float m24,
                      float m31, float m32, float m33, float m34,
                      float m41, float m42, float m43, float m44)
        {
            this.M11 = m11; this.M12 = m12; this.M13 = m13; this.M14 = m14;
            this.M21 = m21; this.M22 = m22; this.M23 = m23; this.M24 = m24;
            this.M31 = m31; this.M32 = m32; this.M33 = m33; this.M34 = m34;
            this.M41 = m41; this.M42 = m42; this.M43 = m43; this.M44 = m44;
        }

        /// <summary>
        /// Gets and sets the translation vector of the Matrix.
        /// </summary>
        public Vector3 Translation 
        {
            get
            {
                return new Vector3(this.M41, this.M42, this.M43);
            }
            set
            {
                this.M41 = value.X;
                this.M42 = value.Y;
                this.M43 = value.Z;
            }
        }

        /// <summary>
        /// Creates a translation Matrix. 
        /// </summary>
        /// <param name="xPosition">Value to translate by on the x-axis.</param>
        /// <param name="yPosition">Value to translate by on the y-axis.</param>
        /// <param name="zPosition">Value to translate by on the z-axis.</param>
        /// <returns>The created translation Matrix.</returns>
        public static Matrix CreateTranslation(float xPosition, float yPosition, float zPosition)
        {
            return new Matrix() 
            { 
                Translation = new Vector3(xPosition, 
                                          yPosition, 
                                          zPosition)
            };
        }

        /// <summary>
        /// Transforms a 3D vector by the given matrix.
        /// </summary>
        /// <param name="position">The source vector.</param>
        /// <param name="matrix">The transformation matrix.</param>
        /// <returns>The transformed vector.</returns>
        public static Vector3 Transform(Vector3 position, Matrix matrix)
        {
            //
            // assume matrix is affine.
            //
            return new Vector3(position.X * matrix.M11 + position.Y * matrix.M21 + position.Z * matrix.M31 + matrix.M41,
                               position.X * matrix.M12 + position.Y * matrix.M22 + position.Z * matrix.M32 + matrix.M42,
                               position.X * matrix.M13 + position.Y * matrix.M23 + position.Z * matrix.M33 + matrix.M43);
        }

        /// <summary>
        /// Returns an instance of the identity matrix.
        /// </summary>
        public static Matrix Identity 
        {
            get
            {
                return new Matrix(1, 0, 0, 0,
                                  0, 1, 0, 0,
                                  0, 0, 1, 0,
                                  0, 0, 0, 1);
            }
        }
    }
}
